﻿/*******************************************************************************
Copyright (c) 2011-2013, PKStudio
Copyright (c) 2011,      Zynga Inc.
Copyright (c) 2008-2010, Ricardo Quesada

http://pkstudio.org

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*******************************************************************************/

using System;
using System.Drawing;

namespace PKEngine
{
	/// <summary>
	/// Instant actions are immediate actions. They don't have a duration like the PKActionInterval.
	/// </summary>
	public class PKActionInstant : PKFiniteTimeAction
	{
		#region Public Properties
		/// <summary>
		/// Return true if the action has finished.
		/// </summary>
		public override bool IsDone
		{
			get
			{
				return true;
			}
		}
		#endregion

		#region Initialization
		public PKActionInstant()
			: base()
		{
			this.Duration = 0;
		}
		#endregion

		#region Public Methods
		public override void Step(float dt)
		{
			this.Update(1);
		}
		#endregion
	}

	/// <summary>
	/// Show the node.
	/// </summary>
	public class PKShow : PKActionInstant
	{
		#region Initialization
		public PKShow()
			: base()
		{
		}
		#endregion

		#region Public Methods
		public override void Update(float time)
		{
			Target.IsVisible = true;
		}

		public override PKFiniteTimeAction Reverse()
		{
			return new PKHide();
		}

		public override PKFiniteTimeAction Copy()
		{
			return new PKShow();
		}
		#endregion
	}

	/// <summary>
	/// Hide the node.
	/// </summary>
	public class PKHide : PKActionInstant
	{
		#region Initialization
		public PKHide()
			: base()
		{
		}
		#endregion

		#region Public Methods
		public override void Update(float time)
		{
			Target.IsVisible = false;
		}

		public override PKFiniteTimeAction Reverse()
		{
			return new PKShow();
		}

		public override PKFiniteTimeAction Copy()
		{
			return new PKHide();
		}
		#endregion
	}

	/// <summary>
	/// Toggles the visibility of a node.
	/// </summary>
	public class PKToggleVisibility : PKActionInstant
	{
		#region Initialization
		public PKToggleVisibility()
			: base()
		{
		}
		#endregion

		#region Public Methods
		public override void Update(float time)
		{
			Target.IsVisible = !Target.IsVisible;
		}

		public override PKFiniteTimeAction Reverse()
		{
			return new PKToggleVisibility();
		}

		public override PKFiniteTimeAction Copy()
		{
			return new PKToggleVisibility();
		}
		#endregion
	}

	/// <summary>
	/// Places the node in a certain position.
	/// </summary>
	public class PKPlace : PKActionInstant
	{
		#region Private Fields
		private Point position;
		#endregion

		#region Initialization
		public PKPlace(Point position)
			: base()
		{
			this.position = position;
		}
		#endregion

		#region Public Methods
		public override void Update(float time)
		{
			Target.Position = position;
		}

		public override PKFiniteTimeAction Copy()
		{
			return new PKPlace(position);
		}
		#endregion
	}

	/// <summary>
	/// Delegate for CallFunc.
	/// </summary>
	public delegate void CallFuncDelegate();

	/// <summary>
	/// Calls a 'callback'.
	/// </summary>
	public class PKCallFunc : PKActionInstant
	{
		#region Public Properties
		public CallFuncDelegate CallbackDelegate { get; set; }
		#endregion

		#region Initialization
		public PKCallFunc(CallFuncDelegate callbackDelegate)
			: base()
		{
			this.CallbackDelegate = callbackDelegate;
		}
		#endregion

		#region Public Methods
		public override void Update(float time)
		{
			this.Execute();
		}

		public void Execute()
		{
			CallbackDelegate();
		}
		#endregion
	}

	/// <summary>
	/// Delegate for CallFuncN.
	/// </summary>
	public delegate void CallFuncNDelegate(PKNode node);

	/// <summary>
	/// Calls a 'callback' with the node as the first argument.
	/// </summary>
	public class PKCallFuncN : PKActionInstant
	{
		#region Public Properties
		public CallFuncNDelegate CallbackDelegate { get; set; }
		#endregion

		#region Initialization
		public PKCallFuncN(CallFuncNDelegate callbackDelegate)
			: base()
		{
			this.CallbackDelegate = callbackDelegate;
		}
		#endregion

		#region Public Methods
		public override void Update(float time)
		{
			this.Execute();
		}

		public void Execute()
		{
			CallbackDelegate(Target);
		}
		#endregion
	}

	/// <summary>
	/// Delegate for CallFuncD.
	/// </summary>
	public delegate void CallFuncDDelegate(object data);

	/// <summary>
	/// Calls a 'callback' with the data as the argument.
	/// </summary>
	public class PKCallFuncD : PKActionInstant
	{
		#region Public Properties
		public CallFuncDDelegate CallbackDelegate { get; set; }
		public object Data { get; set; }
		#endregion

		#region Initialization
		public PKCallFuncD(CallFuncDDelegate callbackDelegate, object data)
			: base()
		{
			this.CallbackDelegate = callbackDelegate;
			this.Data = data;
		}
		#endregion

		#region Public Methods
		public override void Update(float time)
		{
			this.Execute();
		}

		public void Execute()
		{
			CallbackDelegate(Data);
		}
		#endregion
	}

	/// <summary>
	/// Delegate for CallFuncND.
	/// </summary>
	public delegate void CallFuncNDDelegate(PKNode node, object data);

	/// <summary>
	/// Calls a 'callback' with the node as the first argument and the 2nd argument is data.
	/// </summary>
	public class PKCallFuncND : PKActionInstant
	{
		#region Public Properties
		public CallFuncNDDelegate CallbackDelegate { get; set; }
		public object Data { get; set; }
		#endregion

		#region Initialization
		public PKCallFuncND(CallFuncNDDelegate callbackDelegate, object data)
			: base()
		{
			this.CallbackDelegate = callbackDelegate;
			this.Data = data;
		}
		#endregion

		#region Public Methods
		public override void Update(float time)
		{
			this.Execute();
		}

		public void Execute()
		{
			CallbackDelegate(Target, Data);
		}
		#endregion
	}
}
